///////////////////////////////////////////////////////////////////////////////

#ifndef _SERVERBATTLEFIELD_H_
#define _SERVERBATTLEFIELD_H_

////////////////////////////////////////////////////////////////////////////////

#ifndef _SERVERSTATE_H_
#include "serverstate.h"
#endif

#ifndef _SERVERINFO_H_
#include "serverinfo.h"
#endif

#ifndef _SPLAYER_H_
#include "splayer.h"
#endif

#ifndef _SBULLET_H_
#include "sbullet.h"
#endif

#ifndef _SWALL_H_
#include "swall.h"
#endif

#ifndef _PHYSICSENGINE_H_
#include "physicsengine.h"
#endif

////////////////////////////////////////////////////////////////////////////////

class Physics;
struct MapOnServer;

////////////////////////////////////////////////////////////////////////////////


/** Battlefield representation on server side.
*   Manages all objects on the game.
*
*  @author   Roman Pasechnik
*  @author   Anastasia Karpinska
*  @since    Nov 07th, 2009
*  @updated  May 03rd, 2010
*/
class ServerBattlefield
{
////////////////////////////////////////////////////////////////////////////////

public:

////////////////////////////////////////////////////////////////////////////////


    /** Constructor */
    ServerBattlefield( ServerEngine* _serverEngine );


    /** Destructor */
    ~ServerBattlefield();


////////////////////////////////////////////////////////////////////////////////


    /** Get server state */
    ServerState GetState() const;


////////////////////////////////////////////////////////////////////////////////


    /** Update battlefield state */
    void Update( size_t _dt );


    /** Tells is there such player in the battlefield */
    bool HasPlayer( int _playerID ) const;


    /** Get existing player by ID */
    SPlayer& GetPlayer( int _ID );
    const SPlayer& GetPlayer( int _ID ) const;


    /** Add player */
    void AddPlayer( int _ID );


    /** Remove player */
    void RemovePlayer( int _ID );


    /** Set client input */
    void SetClientInput( int _clientID, const ClientInput& _input, size_t _creationTime );


////////////////////////////////////////////////////////////////////////////////
//// Collision processing
////////////////////////////////////////////////////////////////////////////////


    /** Informs this object about collision with other object */
    void CollideBulletWithPlayer( SBullet& _bullet, SPlayer& _player );


////////////////////////////////////////////////////////////////////////////////


    /** Set battle field map */
    void SetMap( MapOnServer& _map );


////////////////////////////////////////////////////////////////////////////////


    /** Gets physics engine */
    PhysicsEngine& Physics();


////////////////////////////////////////////////////////////////////////////////

private:

////////////////////////////////////////////////////////////////////////////////

    /** Process player's shooting */
    void ProcessUserInput( size_t _dt );


    /** Update engine physic state */
    void UpdatePhysics( size_t _dt );


    /** Delete bullets outside of the field */
    void DeleteBullets();


    /** Reset died players */
    void ResetPlayers();


    /** Choose random start player position */
    const Point& ChoosePosition() const;


    /** Create walls from map */
    template< typename _TColl >
    void CreateWalls( _TColl& _coll );


////////////////////////////////////////////////////////////////////////////////


    /** [Utility type]: Players by identifiers */
    typedef std::map<int, SPlayer> SPlayersByIDs;


    /** Prevents creating more bullets, then could be placed in buffer and sent to client */
    enum { MAX_BULLET_COUNT = 64};


    /** Players by ids */
    SPlayersByIDs m_SPlayersByIDs;


    /** Flying bullets */
    SBulletsList m_Bullets;


    /** Walls */
    SWallsList m_Walls;


    /** List of revival points for players */
    Points m_RevivalPoints;


    /** Field width */
    float m_Width;


    /** Field height */
    float m_Height;


    /** Physics engine */
    PhysicsEngine m_PhysicsEngine;


    /** Server engine */
    ServerEngine* m_ServerEngine;


////////////////////////////////////////////////////////////////////////////////

};

////////////////////////////////////////////////////////////////////////////////

#endif

////////////////////////////////////////////////////////////////////////////////
